#include "actioninput.h"
#include <QtGui>
#include <QtCore>
#include <QApplication>
#include <Windows.h>


ActionInput::ActionInput()
{
    classname = __FUNCTION__;
    actParam = QJsonObject();
}

ActionInput::ActionInput(QString text, bool paste)
{
    classname = __FUNCTION__;
    actParam = QJsonObject();
    actParam.insert("text",text);
    actParam.insert("paste",paste?1:0);
}

ExecuteRet ActionInput::execute()
{
    QString text = actParam.value("text").toString();
    bool paste = (actParam.value("paste").toInt()==1);
    qInfo()<<classname<<"input text"<<text<<"isPaste"<<paste;
    if(text.isEmpty()){
        message = "input text is empty.";
        return ERError;
    }

    if(paste)
    {
        INPUT input[4];
        memset(input,0,sizeof(INPUT)*4);
        int inputIndex = 0;
        DWORD timestamp = 1;
        QClipboard *cb = QApplication::clipboard();
        QString oldText = cb->text();
        qDebug()<<"clipboard old"<<oldText;
        cb->setText(text);
        QThread::msleep(50);

        input[inputIndex].type = INPUT_KEYBOARD;
        input[inputIndex].ki.dwFlags = 0;
        input[inputIndex].ki.wVk = VK_CONTROL;
        input[inputIndex].ki.time = timestamp;
        ++inputIndex; timestamp+=10;

        input[inputIndex].type = INPUT_KEYBOARD;
        input[inputIndex].ki.dwFlags = 0;
        input[inputIndex].ki.wVk = 'V';  //'V'
        input[inputIndex].ki.time = timestamp;
        ++inputIndex; timestamp+=10;

        input[inputIndex].type = INPUT_KEYBOARD;
        input[inputIndex].ki.dwFlags = KEYEVENTF_KEYUP;
        input[inputIndex].ki.wVk = 'V';  //'V'
        input[inputIndex].ki.time = timestamp;
        ++inputIndex; timestamp+=10;

        input[inputIndex].type = INPUT_KEYBOARD;
        input[inputIndex].ki.dwFlags = KEYEVENTF_KEYUP;
        input[inputIndex].ki.wVk = VK_CONTROL;
        input[inputIndex].ki.time = timestamp;
        ++inputIndex; timestamp+=10;

        ::SendInput(inputIndex,input,sizeof(INPUT));

        //稍作等待，把原剪贴板恢复.
        //for(int w=0;w<inputIndex;w++)
        //{
            QThread::msleep(500);
        //    QApplication::processEvents();
       // }
        cb->setText(oldText);
        return ERSucc;
    }
    else
    {
        return charecterInput(text);
    }

    Q_ASSERT(false);
    return ERError;
}

//VK_ADD~~VK_OEM_PLUS     VK_MULTIPLY~~shift+8
static const uint8_t AscVk[128] = {  //asc码对应的VK（基础）码.
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    VK_SPACE, '1', VK_OEM_7, '3', '4', '5', '7', VK_OEM_7, '9', '0', VK_MULTIPLY, VK_ADD, VK_OEM_COMMA, VK_OEM_MINUS, VK_OEM_PERIOD, VK_OEM_2,  //空格到斜杠
    '0','1','2','3','4','5','6','7','8','9',VK_OEM_1,VK_OEM_1,VK_OEM_COMMA,VK_OEM_PLUS,VK_OEM_PERIOD,VK_OEM_2,
    '2', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
    'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', VK_OEM_4,VK_OEM_5,VK_OEM_6,'6',VK_OEM_MINUS,
    VK_OEM_3,'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
    'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', VK_OEM_4,VK_OEM_5,VK_OEM_6,VK_OEM_3,0
};
static const uint8_t ShfMk[128] = {  //asc码对应，标记是否要shift
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0
};

//考虑兼容性最佳，使用按键老老实实.
ExecuteRet ActionInput::charecterInput(QString text)
{
    QByteArray txt = text.toLocal8Bit();
    if(txt.length()>64){
        message = "text too long, <=64";
        return ERError;
    }

    const int maxCount = txt.length()*4;
    INPUT *inputs = new INPUT[maxCount];
    memset(inputs,0,sizeof(INPUT)*maxCount);
    int inputIndex = 0;
    DWORD timestamp = 1;
    for(int i=0;i<txt.length();i++)
    {
        char c = txt.at(i);
        uint8_t vk = AscVk[c];
        if(vk == 0){
            message = text + "invalid char";
            return ERError;
        }

        if(ShfMk[c])
        {
            inputs[inputIndex].type = INPUT_KEYBOARD;
            inputs[inputIndex].ki.dwFlags = 0;
            inputs[inputIndex].ki.wVk = VK_SHIFT;
            inputs[inputIndex].ki.time = timestamp;
            ++inputIndex; timestamp+=10;
        }

        inputs[inputIndex].type = INPUT_KEYBOARD;
        inputs[inputIndex].ki.dwFlags = 0;
        inputs[inputIndex].ki.wVk = vk;
        inputs[inputIndex].ki.time = timestamp;
        ++inputIndex; timestamp+=10;

        inputs[inputIndex].type = INPUT_KEYBOARD;
        inputs[inputIndex].ki.dwFlags = KEYEVENTF_KEYUP;
        inputs[inputIndex].ki.wVk = vk;
        inputs[inputIndex].ki.time = timestamp;
        ++inputIndex; timestamp+=10;

        if(ShfMk[c])
        {
            inputs[inputIndex].type = INPUT_KEYBOARD;
            inputs[inputIndex].ki.dwFlags = KEYEVENTF_KEYUP;
            inputs[inputIndex].ki.wVk = VK_SHIFT;
            inputs[inputIndex].ki.time = timestamp;
            ++inputIndex; timestamp+=10;
        }
    }
    ::SendInput(inputIndex,inputs,sizeof(INPUT));

    //for(int w=0;w<inputIndex;w++)
    //{
    //qDebug()<<"tick"<<GetTickCount();
    QThread::msleep(500);
    //QApplication::processEvents();
    //}

    delete[] inputs;

    return ERSucc;
}
